{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "73bd968b-d970-4a05-94ef-4e7abf990827",
   "metadata": {},
   "source": [
    "Chapter 05\n",
    "\n",
    "# 爱因斯坦求和约定\n",
    "Book_4《矩阵力量》 | 鸢尾花书：从加减乘除到机器学习 (第二版)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05612796-d376-409c-bb07-3da0f851fa29",
   "metadata": {},
   "source": [
    "这段代码使用 `numpy` 库的 `einsum` 函数进行各种矩阵和向量的运算。`einsum` 函数的主要优势在于其高效的索引处理方式，使得许多复杂的矩阵和向量操作可以用简单的字符串表达式来实现。这段代码包括以下几个主要部分：\n",
    "\n",
    "1. **定义向量与矩阵**：  \n",
    "   定义了两个列向量\n",
    "\n",
    "   $$ a = \\begin{bmatrix} 1 \\\\ 2 \\\\ 3 \\end{bmatrix} $$\n",
    "   $$ b = \\begin{bmatrix} -4 \\\\ -5 \\\\ -6 \\end{bmatrix} $$\n",
    "\n",
    "   以及它们对应的一维向量形式 \\( a_{1D} = [1, 2, 3] \\) 和 \\( b_{1D} = [-4, -5, -6] \\)。\n",
    "\n",
    "3. **向量和矩阵的求和**：  \n",
    "   使用 `einsum('ij->', a)` 计算 \\( a \\) 中所有元素的和，即 \\( \\sum_{i,j} a_{ij} \\)。  \n",
    "   同样地，`einsum('i->', a_{1D})` 计算 \\( a_{1D} \\) 的元素和，即 \\( \\sum_i a_{i} \\)。\n",
    "\n",
    "4. **逐元素乘积**：  \n",
    "   使用 `einsum('ij,ij->ij', a, b)` 计算 \\( a \\) 和 \\( b \\) 的逐元素乘积，其结果为一个矩阵，其中每个元素 \\( (i,j) \\) 对应 \\( a_{ij} \\times b_{ij} \\)。  \n",
    "   对一维向量 `a_1D` 和 `b_1D` 的逐元素乘积，则通过 `einsum('i,i->i', a_{1D}, b_{1D})` 实现，得到 \\( [a_1 \\times b_1, a_2 \\times b_2, a_3 \\times b_3] \\)。\n",
    "\n",
    "5. **向量的内积**：  \n",
    "   使用 `einsum('ij,ij->', a, b)` 计算 \\( a \\) 和 \\( b \\) 的内积，即 \\( \\sum_{i,j} a_{ij} \\cdot b_{ij} \\)。  \n",
    "   类似地，对于一维向量的内积，通过 `einsum('i,i->', a_{1D}, b_{1D})` 计算，公式为 \\( \\sum_i a_i \\cdot b_i \\)。\n",
    "\n",
    "6. **向量的外积**：  \n",
    "   `einsum('ij,ji->ij', a, a)` 计算向量 \\( a \\) 自身的外积，生成一个矩阵，每个元素为 \\( a_{ij} \\cdot a_{ji} \\)。  \n",
    "   而 `einsum('i,j->ij', a_{1D}, a_{1D})` 计算 \\( a_{1D} \\) 的外积，得到一个 \\( 3 \\times 3 \\) 矩阵，其元素为 \\( a_i \\cdot a_j \\)。\n",
    "\n",
    "7. **矩阵的定义及运算**：  \n",
    "   定义了两个 \\( 3 \\times 3 \\) 的矩阵 \\( A \\) 和 \\( B \\)。矩阵 \\( A \\) 和 \\( B \\) 之间的运算包括以下内容：  \n",
    "   \n",
    "   - **转置**： `einsum('ji', A)` 计算 \\( A \\) 的转置。\n",
    "   \n",
    "   - **矩阵求和**： `einsum('ij->', A)` 计算矩阵 \\( A \\) 所有元素的和。  \n",
    "   \n",
    "   - **按行和按列求和**：  \n",
    "     使用 `einsum('ij->j', A)` 计算每列的和，结果为一个一维数组，形式为 \\( \\sum_i A_{ij} \\)。  \n",
    "     `einsum('ij->i', A)` 计算每行的和，结果形式为 \\( \\sum_j A_{ij} \\)。\n",
    "\n",
    "   - **提取主对角线和计算迹**：  \n",
    "     `einsum('ii->i', A)` 提取 \\( A \\) 的主对角线元素，结果为 \\( [A_{11}, A_{22}, A_{33}] \\)。  \n",
    "     `einsum('ii->', A)` 计算矩阵 \\( A \\) 的迹 \\( \\text{tr}(A) = \\sum_i A_{ii} \\)。\n",
    "\n",
    "   - **矩阵乘法和结果求和**：  \n",
    "     `einsum('ij,jk->ik', A, B)` 计算 \\( A \\) 和 \\( B \\) 的矩阵乘积 \\( C = A \\times B \\)，即 \\( C_{ik} = \\sum_j A_{ij} \\cdot B_{jk} \\)。  \n",
    "     `einsum('ij,jk->', A, B)` 计算 \\( A \\times B \\) 的所有元素和。  \n",
    "     `einsum('ij,jk->ki', A, B)` 先进行矩阵乘法，再对结果转置。\n",
    "\n",
    "   - **逐元素乘积**：  \n",
    "     `einsum('ij,ij->ij', A, B)` 计算 \\( A \\) 和 \\( B \\) 的逐元素乘积，结果为矩阵 \\( D \\)，其中 \\( D_{ij} = A_{ij} \\cdot B_{ij} \\)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "97fcb029-de43-4a4b-ba5f-ad331b7a78eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a4e312b-9e45-4be6-afcc-83060d1798ee",
   "metadata": {},
   "source": [
    "## 定义矩阵和向量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "b8e03123-64d1-4387-8fc7-6e7464e5a529",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([[1],\n",
    "              [2],\n",
    "              [3]])  # 定义列向量 a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c691db9b-31d1-4661-ac0b-17f39e31bddb",
   "metadata": {},
   "outputs": [],
   "source": [
    "a_1D = np.array([1,2,3])  # 定义一维向量 a_1D"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "6f95f355-f84a-4476-a424-89279c00eab2",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.array([[-4],\n",
    "              [-5],\n",
    "              [-6]])  # 定义列向量 b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "9868ad35-72ff-4e73-b364-02186f82ddde",
   "metadata": {},
   "outputs": [],
   "source": [
    "b_1D = np.array([-4,-5,-6])  # 定义一维向量 b_1D"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da290670-c5b3-45fb-90b9-d2260356cb7f",
   "metadata": {},
   "source": [
    "## 计算向量 a 的元素和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "ce155c35-ebdc-4fb7-9036-b64a5e7c51c5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij->',a))  # 计算矩阵 a 所有元素的和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fc84a3f0-61a5-4a06-af67-dc92507acf20",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('i->',a_1D))  # 计算向量 a_1D 所有元素的和"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3fe87ea0-03ac-4f71-8571-8ae0ed8a5269",
   "metadata": {},
   "source": [
    "## 向量 a 和 b 的逐元素乘积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bc000421-7392-4603-8fe8-aa6608e1c1cb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ -4]\n",
      " [-10]\n",
      " [-18]]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij,ij->ij',a,b))  # 计算矩阵 a 和 b 的逐元素乘积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "bb28fdab-b2b0-4d28-8f62-1453d77bfbb4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ -4 -10 -18]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('i,i->i',a_1D,b_1D))  # 计算向量 a_1D 和 b_1D 的逐元素乘积"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aee84a7c-d65b-440a-967b-ac45f0c28acd",
   "metadata": {},
   "source": [
    "## 向量 a 和 b 的内积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "34d92cbc-b818-409d-ab86-d075c27236cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-32\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij,ij->',a,b))  # 计算矩阵 a 和 b 的内积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "3142feb7-5501-49de-9576-a3c010cbb4be",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-32\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('i,i->',a_1D,b_1D))  # 计算向量 a_1D 和 b_1D 的内积"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f19a1dbf-204b-4d08-bb7f-89fe08a5a40f",
   "metadata": {},
   "source": [
    "## 向量 a 自身的外积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "e46e5895-d71d-4eed-a6ae-4c6875da71bb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [2 4 6]\n",
      " [3 6 9]]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij,ji->ij',a,a))  # 计算矩阵 a 和自身的外积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1568a79b-9345-474a-aa5a-a977ef5ead8f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [2 4 6]\n",
      " [3 6 9]]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('i,j->ij',a_1D,a_1D))  # 计算向量 a_1D 和自身的外积"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8cf3e0c-da91-4cb8-885e-145cc69b2bb3",
   "metadata": {},
   "source": [
    "## 向量 a 和 b 的外积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "442d8342-ac8e-4b31-8dd7-ab0c8704c3ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(np.einsum('ij,ji->ij',a,b))  # 计算矩阵 a 和 b 的外积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81954884-d255-4524-b09b-2848891ef7e7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ -4  -5  -6]\n",
      " [ -8 -10 -12]\n",
      " [-12 -15 -18]]\n",
      "[[ -4  -5  -6]\n",
      " [ -8 -10 -12]\n",
      " [-12 -15 -18]]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('i,j->ij',a_1D,b_1D))  # 计算向量 a_1D 和 b_1D 的外积"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f897baa-6fca-4bf5-9613-9379363878b8",
   "metadata": {},
   "source": [
    "## 定义方阵 A 和 B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "31dd6b69-fc1a-4613-a3bc-f5cb51988014",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1,2,3],\n",
    "              [4,5,6],\n",
    "              [7,8,9]])  # 定义方阵 A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "08d16cb0-a5cb-4b32-8f2e-fc8cf5f2a206",
   "metadata": {},
   "outputs": [],
   "source": [
    "B = np.array([[-1,-4,-7],\n",
    "              [-2,-5,-8],\n",
    "              [-3,-6,-9]])  # 定义方阵 B"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccad52d1-dc84-4b3c-a097-3380f3ec90a6",
   "metadata": {},
   "source": [
    "## A 的转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "12e193cf-71e4-48b0-8cbb-cbcf3ccdbc6c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 4 7]\n",
      " [2 5 8]\n",
      " [3 6 9]]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ji',A))  # 计算矩阵 A 的转置"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1528a603-b271-4274-9f83-045fe64a99db",
   "metadata": {},
   "source": [
    "## A 的元素和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "2d6b2be7-e73a-46b1-9415-944930809770",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "45\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij->',A))  # 计算矩阵 A 所有元素的和"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "257c86ae-4793-4f91-9bfc-6128b1c9aa01",
   "metadata": {},
   "source": [
    "## 按行求和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "7cef1bf8-aed8-4f0a-b97b-8758d33075da",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[12 15 18]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij->j',A))  # 计算矩阵 A 的每列的和"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58267372-554b-4284-92c1-cee2453df11e",
   "metadata": {},
   "source": [
    "## 按列求和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "595287a8-6e24-408e-8552-aa7ecc6fc55f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 6 15 24]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij->i',A))  # 计算矩阵 A 的每行的和"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d64a84cf-72a0-408d-b896-c3b88087dbf7",
   "metadata": {},
   "source": [
    "## 提取主对角线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "200ca6b1-c240-4d6d-a8c2-f3fd64763bea",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 5 9]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ii->i',A))  # 提取矩阵 A 的主对角线元素"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b786c9a-5864-451f-906c-0f14253e5aad",
   "metadata": {},
   "source": [
    "## 计算矩阵 A 的迹"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "9e3a19a5-0f54-4dfe-829c-be92fd12aa7b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ii->',A))  # 计算矩阵 A 的迹（主对角线元素的和）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05751e89-a555-438c-898a-bf925c4f66b4",
   "metadata": {},
   "source": [
    "## 矩阵 A 和 B 的乘积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "64413023-b87d-4a78-b275-cfd84e257fc4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ -14  -32  -50]\n",
      " [ -32  -77 -122]\n",
      " [ -50 -122 -194]]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij,jk->ik', A, B))  # 计算矩阵 A 和 B 的矩阵乘法"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3af4c95f-aa69-49cb-a2ce-aab8772b09c4",
   "metadata": {},
   "source": [
    "## A 和 B 的矩阵乘积的所有元素和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "7c47a0c5-20af-4bb1-96e8-56c601115c6a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-693\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij,jk->', A, B))  # 计算矩阵 A 和 B 的乘积矩阵的所有元素的和"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a85f940b-b6bd-483e-8ddb-9cab6ee24ce0",
   "metadata": {},
   "source": [
    "## 矩阵相乘后转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "56598ed4-fd7a-4f82-ab5b-573f72f966a2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ -14  -32  -50]\n",
      " [ -32  -77 -122]\n",
      " [ -50 -122 -194]]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij,jk->ki', A, B))  # 计算矩阵 A 和 B 的乘积后对结果转置"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ade29c2-f09c-420a-a4e4-ef3aba2aac18",
   "metadata": {},
   "source": [
    "## A 和 B 的逐元素乘积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "d5e5fe17-96cd-4c6d-8326-da9f6df6ac1f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ -1  -8 -21]\n",
      " [ -8 -25 -48]\n",
      " [-21 -48 -81]]\n"
     ]
    }
   ],
   "source": [
    "print(np.einsum('ij,ij->ij', A, B))  # 计算矩阵 A 和 B 的逐元素乘积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "85a80909-2aac-49ed-bb7a-f8cc6b80ee7d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ecd322f4-f919-4be2-adc3-69d28ef25e69",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
